<?php
/*
  +----------------------------------------------------------------------+
  | UCModStore.php                                                       |
  +----------------------------------------------------------------------+
  | Copyright (c) 2010 snda.com - Web Development Center                 |
  +----------------------------------------------------------------------+
  | UC Store                                                             |
  +----------------------------------------------------------------------+
  | Authors: normal <normal@normal.com>                                  |
  +----------------------------------------------------------------------+
*/
class UCModStore
{
	public $_apcttl;
	public $_mcttl;
	private static $instance = null;
    private $_included = false;
    
    public function __construct()
    {
		if( !$this->_included ) {
			require_once(dirname(__FILE__).'/../../config/UCConfStore.php');
			require_once(dirname(__FILE__).'/../../libraries/UCLibPDOFactory.php');
			require_once(dirname(__FILE__).'/../../libraries/UCLibCache.php');
			require_once(dirname(__FILE__).'/../../libraries/UCLibStat.php');
			require_once(dirname(__FILE__).'/../../models/relation/UCModRelation.php');
			require_once(dirname(__FILE__).'/../../models/store/UCModPanel.php');
			require_once(dirname(__FILE__).'/../user/UCModUserInfo.php');
			$this->_included = true;
		}

		if(defined('__UC_ENV') && (__UC_ENV == 'TEST' || __UC_ENV == 'DEV'))
		{
			$this->_apcttl = 60;
			$this->_mcttl = 604800;
		}else{
			$this->_apcttl = 60;	//one minute
			$this->_mcttl = 604800;	//one week
		}
    }

	public static function getInstance(){
		if(self::$instance == null){		
			self::$instance = new self;
		}
			
		return self::$instance;
	}

	private function _getApp($appid)
	{
		if(!is_numeric($appid))
			return false;

		//read from apc cache
		$cachekey = 'appstore_depository' . $appid;
        if (function_exists("apc_store")) 
		    $app = apc_fetch($cachekey, &$apcret);
		if($apcret)
			return $app;

		//read from memcache
		$cache = new UCLibCache('appstore');
		$app = $cache->read($cachekey);
		if(false !== $app)
		{
            if (function_exists("apc_store"))
			    apc_store($cachekey, $app, $this->_apcttl);
			return $app;
		}

		//read from database
		$pdo = UCLibPDOFactory::getPDO('appstore_depository', $appid, "store2dbconfig");
		$app = $pdo->query_one_row_with_prepare("SELECT id, title, link, ext FROM $pdo->database.$pdo->table WHERE id = ?", array($appid));
		if(false === $app)
			return false;

		if(is_null($app))
		{
			//use NULL as a mark when the record is not found
			$cache->write($cachekey, null, $this->_mcttl);
            if (function_exists("apc_store"))
			    apc_store($cachekey, $app, null);
			return false;
		}

		if(isset($app['ext']) && $app['ext'] != '')
			$app['ext'] = json_decode($app['ext'], true);
		else
			unset($app['ext']);

		//write to memcache
		$cache->write($cachekey, $app, $this->_mcttl);
        if (function_exists("apc_store"))
		    apc_store($cachekey, $app, $this->_apcttl);

		return $app;
	}

	public function getApp($appid)
	{
		if(is_array($appid))
		{
			$tmp = array();
			foreach($appid as $id => $val)
			{
				if(!is_array($val))
					$id = $val;

				$tmp[$id] = $this->_getApp($id);
				if(false == $tmp[$id])
					unset($tmp[$id]);
			}

			return $tmp;

		}elseif(is_numeric($appid)){
			return $this->_getApp($appid);
		}
	}

	public function getApps($appid)
	{
		return $this->getApp($appid);
	}

	public function getGeneralAppid()
	{
		$time = microtime(true) * 100000;
		$rand = mt_rand();
		$size = 4;
		$l = strlen($rand);
		if ($l > $size) $rand = substr($rand, $l - $size);
		else if ($size > $l) $rand = str_repeat('0', $size - $l) . $rand;
		return $time.$rand;
	}

	public function insertApp($app)
	{
		if(!is_array($app))
			return false;
		
		if(isset($app['id']) && $app['id'] == 0)
			$app['id'] = $this->getGeneralAppid();

		$ext = '';
		if(isset($app['ext']) && is_array($app['ext']))
			$ext = json_encode($app['ext']);

		$pdo = UCLibPDOFactory::getPDO('appstore_depository', $app['id'], "store2dbconfig");
		$ret = $pdo->exec_with_prepare("INSERT INTO $pdo->database.$pdo->table (id, title, link, ext)VALUES(?, ?, ?, ?)", array($app['id'], $app['title'], $app['link'], $ext));
		if(false === $ret)
			return false;

		//write to cache
		$cachekey = 'appstore_depository' . $app['id'];
		$cache = new UCLibCache('appstore');
		$cache->write($cachekey, $app, $this->_mcttl);

		return true;
	}

	public function updateIcon($appId) {		
		$existing = $this->getApp($appId);
		if (!$existing) return false;

		$iconver = false;

		if(isset($existing['ext']) && is_array($existing['ext'])) {
			$iconver = $existing['ext']["iconver"];
		}

		if ($iconver) $iconver = $iconver + 1;
		else $iconver = 1;

		if(isset($existing['ext']) && is_array($existing['ext'])) {
			$existing['ext']["iconver"] = $iconver;
		} else {
			$existing['ext'] = array("iconver" => $iconver);
		}

		$ext = json_encode($existing['ext']);

		$pdo = UCLibPDOFactory::getPDO('appstore_depository', $app['id'], "store2dbconfig");
		$ret = $pdo->exec_with_prepare("UPDATE $pdo->database.$pdo->table SET ext = ?, uptime = CURRENT_TIMESTAMP WHERE id = ?", array($ext, $appId));
		if(false === $ret || $ret != 1)
			return false;

		//write to cache
		$cachekey = 'appstore_depository' . $appId;
		$cache = new UCLibCache('appstore');
		$cache->write($cachekey, $existing, $this->_mcttl);

		return true;
	}

	public function setApp($app)
	{
		if(!is_array($app) || !isset($app['id']) || !is_numeric($app['id']) || 0 == $app['id'] || (isset($app['ext']) && !is_array($app['ext']) ))
			return false;

		$existing = $this->getApp($app['id']);
		if (!$existing) return false;

		$iconver = false;

		if(isset($existing['ext']) && is_array($existing['ext'])) {
			$iconver = $existing['ext']["iconver"];
		}

		if ($iconver) {
			if(isset($app['ext']) && is_array($app['ext'])) {
				$app['ext']["iconver"] = $iconver;
			} else {
				$app['ext'] = array("iconver" => $iconver);
			}
		}
		

		$ext = '';
		if(isset($app['ext']) && is_array($app['ext']))
			$ext = json_encode($app['ext']);

		$pdo = UCLibPDOFactory::getPDO('appstore_depository', $app['id'], "store2dbconfig");
		$ret = $pdo->exec_with_prepare("UPDATE $pdo->database.$pdo->table SET id = ?, title = ?, link = ?, ext = ?, uptime = CURRENT_TIMESTAMP WHERE id = ?", array($app['id'], $app['title'], $app['link'], $ext, $app['id']));
		if(false === $ret || $ret != 1)
			return false;

		//write to cache
		$cachekey = 'appstore_depository' . $app['id'];
		$cache = new UCLibCache('appstore');
		$cache->write($cachekey, $app, $this->_mcttl);

		return true;
	}

	public function existApp($appid)
	{
		if(!is_numeric($appid))
			return false;

		$app = $this->_getApp($appid);
		return is_array($app);
	}

	//Show Case ////////////////////////////////////////////////////////////////////////////////////

	public function getShowCase($status = 1, $tag = null, $pagenum = 1, $pagesize = 10)
	{			

		//read from memcache cache
		$cachekey = 'appstore_showcase' . $status . $tag .  $pagenum . $pagesize;
		$cache = new UCLibCache('appstore');
		$ret = $cache->read($cachekey);
		if(false === $ret)
		{
			//read from database
			$pdo = UCLibPDOFactory::getPDO('appstore_showcase', null, "store2dbconfig");
			$ret = $pdo->query_with_prepare("SELECT appid, tag FROM $pdo->database.$pdo->table WHERE status = ? LIMIT ?, ?", array($status, ($pagenum - 1) * $pageisze, $pagesize));
			if(false === $ret)
				return false;

			$cache->write($cachekey, $ret, $this->_mcttl);
		}

		$apps = array();
		foreach($ret as $row)
		{
			$apps[$row['appid']] = $this->_getApp($row['appid']);
			$apps[$row['appid']]['icon32'] = UCModPanel::getIcon($row['appid'], '32');
			$apps[$row['appid']]['icon50'] = UCModPanel::getIcon($row['appid'], '50');
		}

		return $apps;
	}

	//Store Log////////////////////////////////////////////////////////////////////////////////////

	public function setLog($userid, $appid)
	{
		if(!is_numeric($appid) || !is_numeric($userid))
			return false;

		$pdo = UCLibPDOFactory::getPDO('applog_recentapp', $appid, "store2dbconfig");
		$ret = $pdo->exec_with_prepare("UPDATE $pdo->database.$pdo->table SET hits = hits + 1, lasttime = CURRENT_TIMESTAMP WHERE appid = ? AND userid = ?", array($appid, $userid));
		if(false === $ret)
			return false;

		if(1 != $ret)
		{
			$ret = $pdo->exec_with_prepare("INSERT INTO $pdo->database.$pdo->table SET appid = ?, userid = ?, hits = 1, lasttime = CURRENT_TIMESTAMP", array($appid, $userid));
			if(false === $ret)
			{
				return false;
			}
		}

		//clear memcache
		$cachekey = 'applog_recentapp' . $appid;
		$cache = new UCLibCache('applog');
		$cache->delete($cachekey);

		$pdo = UCLibPDOFactory::getPDO('applog_recentuser', $userid, "store2dbconfig");
		$ret = $pdo->exec_with_prepare("UPDATE $pdo->database.$pdo->table SET hits = hits + 1, lasttime = CURRENT_TIMESTAMP WHERE userid = ? AND appid = ?", array($userid, $appid));
		if(false === $ret)
			return false;

		if(1 != $ret)
		{
			$ret = $pdo->exec_with_prepare("INSERT INTO $pdo->database.$pdo->table SET userid = ?, appid = ?, hits = 1, lasttime = CURRENT_TIMESTAMP", array($userid, $appid));
			if(false === $ret)
			{
				return false;
			}
		}

		//clear memcache
		$cachekey = 'applog_recentuser' . $userid;
		$cache = new UCLibCache('applog');
		$cache->delete($cachekey);

		return true;
	}

	public function getAppLog($userid, $appid)
	{
		if(!is_numeric($userid) || !is_numeric($appid))
			return false;

		//read from memcache
		$cachekey = 'applog_recentapp' . $appid;
		$cache = new UCLibCache('applog');
		$ret = $cache->read($cachekey);
		if(false !== $ret)
			return $ret;

		//read from database
		$pdo = UCLibPDOFactory::getPDO('applog_recentapp', $appid, "store2dbconfig");
		$ret = $pdo->query_one_row_with_prepare("SELECT hits, lasttime FROM $pdo->database.$pdo->table WHERE userid = ? AND appid = ? ", array($userid, $appid));
		if(false === $ret)
			return false;

		$cache->write($cachekey, $ret, $this->_mcttl);
		
		return $ret;
	}

	/******************************
	* 获得最近玩过指定应用的用户清单,默认缓存最新的800个用户！每个用户占用35个字节 每个APP占用28K的数据量
	* $appid = APP id号
	* $start = 数据读取开始位置 0～800 之间
	* $limit = 输出多少条数据
	* $usert_id = 当前登录用户的ID，默认为0既当前没有登录用户
	* $avatar = 0/1/2 是否判断头像 0为否 1为输出有头像的 2为输出无头像的
	* $relation = 0/1/2/3/4 关系0为忽略 1为单项好友 2为粉丝 3为双向好友 4为非好友
	* 返回数据array('total'=>总数,'rows'=>array(array('userid'=>用户ID,'hits'=>点击次数,'lasttime'=>最后一次点击时间)))
	***********************************/
	public function getRecentApp($appid, $start=0, $limit = 20, $usert_id = 0, $avatar = 0, $relation=0, $without_info = false)
	{
		if(!is_numeric($appid))
			return false;
			
			$cachekey = md5('applog_user_list_' . $appid);
			$cache = new UCLibCache('applog');
			$ret = $cache->read($cachekey);
			if($ret === false){
				return array('total'=>0,'rows'=>array());
			}
			$ret = explode("&",$ret);
			if(!is_array($ret) || count($ret) == 0){
				return array('total'=>0,'rows'=>array());
			}
			$ids = array();
			foreach($ret as $key=>$val){
				$newval = explode("#",$val);
				if(!is_array($newval) || count($newval) == 0){
					continue;
				}
				$ids[] = trim($newval[0]);
			}
			unset($newval);
			//判断头像
			if($avatar > 0){
				$user_avatar = UCModUserInfo::getUserInfos($ids, array(USERINFO_AVATAR_VERSION));
			}else{
				$user_avatar = array();
			}
			$newret = array();
			foreach($ret as $key=>$val){
				$newval = explode("#",$val);
				$newval = array('userid'=>trim($newval[0]),'hits'=>trim($newval[1]),'lasttime'=>trim($newval[2]));
				if(!is_array($newval) || count($newval) == 0){
					continue;
				}
				if($avatar == 0){
					$newret[] =  $newval;
				}elseif($avatar == 1){
					if($user_avatar[$newval['userid']][USERINFO_AVATAR_VERSION] > 0){
						$newret[] =  $newval;
					}
				}elseif($avatar == 2){
					if($user_avatar[$newval['userid']][USERINFO_AVATAR_VERSION] == 0){
						$newret[] =  $newval;
					}
				}
			}
			unset($newval);
			unset($ret);
			unset($user_avatar);
			if(count($newret) ==0){
				return array('total'=>0,'rows'=>array());
			}
			//判断关系
			if(!empty($usert_id) && !empty($relation)){
				$obj = new UCModRelation($usert_id);
				if($relation == 1 || $relation == 4){
					$userRelat = $obj->getRelationType($ids, 1);
				}elseif($relation == 2){
					$userRelat = $obj->getRelationType($ids, 2);
				}elseif($relation == 3){
					$userRelat = $obj->getRelationType($ids, 3);
				}else{
					$userRelat = $obj->getRelationType($ids, 1);
				}
			}else{
				$userRelat = array();
			}
			$newrets = array();
			foreach($newret as $val){
				if(!empty($usert_id) && ($relation == 1 || $relation == 2 || $relation == 3)){
					if($userRelat[$val['userid']] == 1){
						$newrets[] = $val;
					}
				}elseif(!empty($usert_id) && $relation == 4){
					if($userRelat[$val['userid']] == 0){
						$newrets[] = $val;
					}
				}else{
					$newrets[] = $val;
				}
			}
			unset($newret);
			unset($val);
			unset($ids);
			if(count($newrets) ==0){
				return array('total'=>0,'rows'=>array());
			}
			$total = count($newrets);
			if($limit <= 0){
				$limit = 20;
			}
			if($total < $start){
				$start = $total - $limit;
			}
			if($start < 0){
				$start = 0;
			}
			if($total > $start && $total < ($start+$limit)){
				$limit = $total - $start;
			}
			$rows = array();
			for($i=$start;$i<($start+$limit);$i++){
				$rows[] = $newrets[$i];
			}
			unset($newrets);
			return array('total'=>$total,'rows'=>$rows);
	}
	
	/************************
	* 脚本执行函数 crontab = 10分钟执行一次
	* 读取各应用的用户，并写入CACHE
	* 默认每个应用获取800个用户
	****************************/
	public function getRecentAppDom($limit = 800){
		//读取应用列表，并获得APPID
		$pdo = UCLibPDOFactory::getPDO('appstore_depository', null, "store2dbconfig");
		$ret = $pdo->query_with_prepare("SELECT id FROM $pdo->database.$pdo->table");
		if($ret === false){
			return false;
		}
		$cache = new UCLibCache('applog');
		foreach($ret as $val){
			$pdo = UCLibPDOFactory::getPDO('applog_recentapp', $val['id'], "store2dbconfig");
			$row = $pdo->query_with_prepare("SELECT userid, hits, lasttime FROM $pdo->database.$pdo->table WHERE appid = ? ORDER BY lasttime DESC LIMIT ?,?", array($val['id'],0,$limit));
			//print_r($ret);
			$cachekey = md5('applog_user_list_' . $val['id']);
			if(!is_array($row) || count($row) == 0){
				$cacheList = false;
			}else{
				$listArray = array();
				foreach($row as $rowv){
					$listArray[] = implode("#", $rowv);
				}
				$cacheList = implode("&", $listArray);
				unset($listArray);
			}
			$cache->write($cachekey,$cacheList);
		}
		$cache->close();
		return true;
	}
	

	//获得指定用户最近玩过的应用清单
	public function getRecentUser($userid, $limit = 100, $without_info = false)
	{
		if(!is_numeric($userid))
			return false;

		//read from memcache
		$cachekey = 'applog_recentuser' . $userid;
		$cache = new UCLibCache('applog');
		$ret = $cache->read($cachekey);
		$ret = false;
		if($ret === false){
			$pdo = UCLibPDOFactory::getPDO('applog_recentuser', $userid, "store2dbconfig");
			$ret = $pdo->query_with_prepare("SELECT appid, hits, lasttime FROM $pdo->database.$pdo->table WHERE userid = ? ORDER BY lasttime DESC LIMIT 300", array($userid));
			if(false === $ret){
				$cache->write($cachekey, 'error');
				return false;
			}
			$applist = array();
			if(is_array($ret)){
				foreach($ret as $row){
					$app = $this->_getApp($row['appid']);
					if($app){
						$applist[$row['appid']] = $app;
					}
				}
			}
			$cache->write($cachekey, $applist);
			$ret = $applist;
		}
		if($ret == 'error' || $ret === false){
			return false;
		}
		$ret = array_slice($ret, 0, $limit);
		return $ret;		
	}

	//store helper function//////////////////////////////////////////////////////////////

	/**
	 * 获得在玩某应用的好友(我关注的人）
	 * 
	 * @param int $userid
	 * @param int $appid
	 * @param int $limit
	 * @return array
	 */
	public function getFriendsByApp($userid, $appid, $limit = 10)
	{
		$relation = new UCModRelation($userid);
		$data = $relation->getFollowsDistinct(0, 2000, true);
		if(!$data)
			return false;

		if(isset($data['totalResults']) && $data['totalResults'] == 0)
			return array();

		$i = 0;
		//$panel = new UCModPanel();
		foreach($data['entry'] as $idx => $user)
		{
			/*$panel->setUserId($user['fsdid']);
			if($panel->existApp($appid))
			{
				if(++$i >= $limit)
					break;				
			}else{
				unset($data['entry'][$idx]);
			}*/
			$panel = $this->getRecentUser($user['fsdid']);
			if($panel == false){
				unset($data['entry'][$idx]);
			}elseif(isset($panel[$appid])){
				if(++$i >= $limit)
				break;
			}else{
				unset($data['entry'][$idx]);
			}
		}
		$data = array_slice($data['entry'], 0, $limit);
		return $data;
	}

	public function getConfig($field)
	{
		if(empty($field))
			return false;

		//read from apc cache
		$cachekey = 'appstore_config_' . $field;
        if (function_exists("apc_store"))
		    $value = apc_fetch($cachekey, &$apcret);
		if($apcret)
			return $value;

		//read from memcache cache
		$cache = new UCLibCache('appstore');
		$value = $cache->read($cachekey);
		if(false !== $value)
		{
            if (function_exists("apc_store"))
			    apc_store($cachekey, $value, $this->_apcttl);
			return $value;
		}

		//read from db
		$pdo = UCLibPDOFactory::getPDO('appstore_config', null, "store2dbconfig");
		$value = $pdo->query_one_with_prepare("SELECT value FROM $pdo->database.$pdo->table WHERE field = ?", array($field));
		if(false === $value)
			return false;

		$cache->write($cachekey, $value, $this->_mcttl);
        if (function_exists("apc_store"))
		    apc_store($cachekey, $value, $this->_apcttl);

		return $value;
	}

	public function setConfig($field, $value)
	{
		if(empty($field))
			return false;

		$pdo = UCLibPDOFactory::getPDO('appstore_config', null, "store2dbconfig");
		$ret = $pdo->exec_with_prepare("UPDATE $pdo->database.$pdo->table SET value = ?, uptime = CURRENT_TIMESTAMP WHERE field = ?", array($value, $field));
		if(false === $ret || $ret != 1)
			return false;
		
		$cachekey = 'appstore_config_' . $field;
		
            if (function_exists("apc_store"))
			    apc_store($cachekey, $value, $this->_apcttl);		

		$cache = new UCLibCache('appstore');
		$cache->write($cachekey, $value, $this->_mcttl);

		return true;
	}

	public function isComingSoon(&$app)
	{
		if(isset($app['ext']['comingsoon']) && $app['ext']['comingsoon'] == 1)
			return true;
		else
			return false;
	}

	public function isOffline(&$app)
	{
		if(isset($app['ext']['offline']) && $app['ext']['offline'] == 1)
			return true;
		else
			return false;
	}
    
    public function isShowError(&$app)
    {
        if(isset($app['ext']['showerror']) && $app['ext']['showerror'] == 1)
            return true;
        else
            return false;
    }

	public function getShareAppFromUser1AndUser2($user1, $user2, $limit = 10)
	{
		if(!is_numeric($user1) || !is_numeric($user2))
			return false;

		$panel = new UCModPanel($user1);
		$applist = $panel->get();

		$panel->setUserid($user2);
		$applist2 = $panel->get();

		$applist3 = array_intersect_key($applist, $applist2);
		return array_slice($applist3, 0, $limit);
	}
}